<?php

namespace App\Listeners;

use App\Events\LevelEvent;
use App\Events\MedalEvent;
use App\Events\TaskEvent;
use App\Models\Activity\Code;
use App\Models\Member\CurrencyLog;
use App\Models\Member\Level;
use App\Models\Member\LevelNumberLog;
use App\Models\Member\Member;
use App\Models\Task\Finish;
use App\Models\Task\Task;
use App\Services\Com\LogService;
use App\Services\Com\MessageService;
use App\Services\Member\CurrencyService;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;

class TaskListener
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  TaskEvent  $event
     * @return void
     */
    public function handle(TaskEvent $event)
    {
        $member = Member::where('uuid', $event->member_uuid)->with('attrs')->with('level')->first();
        if(!$member) return;

        if($member->state != 200) return;

        //判断当前任务是否启用
        $task = Task::where('uuid', Task::levelNumberBySourceType()[$event->type]['task_uuid'])->where('state', 1)->where('admin_state', 1)
            ->first();
        if(!$task) return;

        $where = [];
        switch ($task->time_type){
            case 1:  //每日任务
                $where[] = ['created_at', '>=', date('Y-m-d 00:00:00')];
                break;
            case 2:  //每周任务
                $week = date('w') == 0 ? 7 : date('w');
                $where[] = ['created_at', '>=', date('Y-m-d 00:00:00', strtotime('today -' . ($week - 1) . 'day'))];
                break;
            case 3:  //月任务
                $where[] = ['created_at', '>=', date('Y-m-d 00:00:00', strtotime(date('Y-m', time()) . '-01 00:00:00'))];
                break;
            case 4:  //可重复做任务
                $where[] = ['created_at', '=', 1];
                break;
            default:
                break;
        }
        $finish = Finish::where('task_uuid', Task::levelNumberBySourceType()[$event->type]['task_uuid'])->where('member_uuid', $member->uuid)->where($where)->first();

        //当前任务需要主动获取，并且未领取状态 不处理
        if($task->is_get == 2 && !$finish) return;

        //已经完成不需要在处理
        if($finish && $finish->state == 1) return;

        //任务存在，并且小于截至日期（前提有截至时间限制）  未完成，删除任务
        if($finish && $finish->state == 0 && $task->end_time && $task->end_time < date('Y-m-d H:i:s')){
            $finish->update([
                'is_del' => 1,
            ]);

            return;
        }

        switch ($event->type){
            case 1:
                if($member->state == 200 && $member->nickname && $member->avatar_url && $member->introduction && $member->title && $member->desc && $member->background_url && !empty($member->attrs)){
                    $this->updateTask($event, $member, $task, $finish);
                }
                break;
            case 2:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 3:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 4:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 5:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 6:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 7:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 8:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 9:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 10:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 11:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 12:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 13:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 14:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 15:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 16:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 17:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 18:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 19:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 20:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 21:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 22:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 23:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 24:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 25:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 26:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 27:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 28:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 29:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 30:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 31:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 32:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 33:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 34:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 35:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 36:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 37:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 38:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 39:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 40:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 41:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 42:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 43:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 44:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 45:
                $this->updateTask($event, $member, $task, $finish);
                break;
            case 46:
                $this->updateTask($event, $member, $task, $finish);
                break;
        }

    }

    //当完成任务时，更新任务信息
    public function updateTask(TaskEvent $event,Member $member,Task $task, $finish){
        try {
            $before_level_number = $member->level_number;
            DB::beginTransaction();

            //1.更新完成任务数量
            if($finish){
                $finish->finished_num = $finish->finished_num + 1;
                $finish->save();
            }else{
                $finish = Finish::create([
                    'member_uuid' => $member->uuid,
                    'state' => 0,
                    'finished_num' => 1,
                    'is_grant' => 0,
                    'task_uuid' => Task::levelNumberBySourceType()[$event->type]['task_uuid'],
                ]);
            }
            //未完成所有任务，结束进程
            if($finish->finished_num >= $task->num) {
                //是否发放奖励
                $is_grant = $member->level->level >= $task->level ? 1 : 0;
                //1.完成任务更新任务状态 并且更新发放任务状态
                $finish->update([
                    'state' => 1,
                    'is_grant' => $is_grant,
                    'is_del' => $task->finished_del,
                ]);

                if($is_grant){
                    //当需要发放成长值时调用
                    if(Task::levelNumberBySourceType()[$event->type]['level_number'] > 0){
                        //3.添加成长值
                        $after_level_number = bcadd($member->level_number, Task::levelNumberBySourceType()[$event->type]['level_number'], 0);
                        $member->update([
                            'level_number' => $after_level_number
                        ]);

                        event(new MedalEvent(1, $member->uuid));
                        event(new MedalEvent(2, $member->uuid));
                        event(new MedalEvent(3, $member->uuid));


                        //当用户等级升级之后更新用户等级
                        $level = Level::where('number','>=', $member->level_number)->orderBy('number', 'asc')->first();
                        if($level && $level->level > $member->level->level){
                            $member->update([
                                'level_uuid' => $level->uuid
                            ]);
                            // 更新用户等级之后通知等级解锁监听器
                            event(new LevelEvent($member->uuid));

                            $cacheLevels = Cache::get("level_".$member->uuid);
                            $cacheLevels[] = $level;

                            Cache::forever("level_".$member->uuid, $cacheLevels);
                        }

                        //4.增加成长值日志
                        LevelNumberLog::create([
                            'member_uuid' => $member->uuid,
                            'content' => Task::levelNumberBySourceType()[$event->type]['content'],
                            'before_level_number' => $before_level_number,
                            'after_level_number' => $after_level_number,
                            'level_number' => Task::levelNumberBySourceType()[$event->type]['level_number'],
                            'type' => 1,
                            'month' => date('Y-m-01'),
                            'source_type' => Task::levelNumberBySourceType()[$event->type]['source_type'],
                        ]);

                        $cacheTasks = Cache::get("task_".$member->uuid);
                        $cacheTasks[] = Task::levelNumberBySourceType()[$event->type];

                        Cache::put("task_".$member->uuid, $cacheTasks, 60);
                    }

                    $grant = 1; //判断有人数限定任务是否发放奖励，默认发放
                    if($task->join_total_num != 0){
                        $grantNum = Finish::where('task_uuid', Task::levelNumberBySourceType()[$event->type]['task_uuid'])->where('is_grant', 1)->count('*');
                        if($grantNum >= $task->join_total_num) $grant = 0;
                    }

                    //当需要发放积分时调用
                    if(Task::levelNumberBySourceType()[$event->type]['currency'] > 0 && $grant == 1){

                        CurrencyService::income($member->uuid, Task::levelNumberBySourceType()[$event->type]['currency']
                            , Task::levelNumberBySourceType()[$event->type]['source_type'], Task::levelNumberBySourceType()[$event->type]['content']);
//                        //1.添加积分
//                        $after_currency = bcadd($member->currency, Task::levelNumberBySourceType()[$event->type]['currency'], 0);
//
//                        $before_currency = $member->currency;
//                        $member->update([
//                            'currency' => $after_currency,
//                            'total_currency' => bcadd($member->total_currency, Task::levelNumberBySourceType()[$event->type]['currency'], 0),
//                        ]);
//
//                        //2.增加积分日志
//                        CurrencyLog::create([
//                            'member_uuid' => $member->uuid,
//                            'content' => Task::levelNumberBySourceType()[$event->type]['content'],
//                            'before_currency' => $before_currency,
//                            'after_currency' => $after_currency,
//                            'currency' => Task::levelNumberBySourceType()[$event->type]['currency'],
//                            'type' => 1,
//                            'month' => date('Y-m-01'),
//                            'source_type' => Task::levelNumberBySourceType()[$event->type]['source_type'],
//                        ]);

                        $cacheTasks = Cache::get("task_".$member->uuid);
                        $cacheTasks[] = Task::levelNumberBySourceType()[$event->type];

                        Cache::put("task_".$member->uuid, $cacheTasks, 60);

                    }

                    if($grant){
                        //兼容额外特殊奖励
                        switch ($task->id){
                            case 42:
                                $activity_uuid = env('APP_ENV') == 'pro' ? '57f2685d-6b06-4460-bda4-dc7b931c16a4' : 'cc7a3229-2f4d-4eb9-bb74-8b45b9cd7880';  //TODO 上线之后需要配置
                                $code = Code::where('activity_uuid', $activity_uuid)->where('is_send', 0)->where('state', 1)->where('use_num', '>', 0)->first();
                                $code->update(['is_send' => 1]);
                                // 发送消息
                                $message = [];
                                $message['type'] = '112';//您的限时任务即将结束！
                                $message['place'] = '9';// 9是限定任务
                                $message['route_link'] = '/app/ActInfoActivity?params_data='.$activity_uuid;//此任务跳转路由
                                $message['owner_uuid'] = null;//空是系统发
                                $message['time_limit_task_name'] = $task->title;
                                $message['time_limit_task_promo_code'] = $code->code;
                                //接收者
                                $membersUuid = [$member->uuid];
                                MessageService::sendMessage($message, $membersUuid);
                                break;
                            case 43:
                                $activity_uuid = env('APP_ENV') == 'pro' ? '6e10ac94-d3ec-4a8d-b1a3-473f7d7701ad' : '6e10ac94-d3ec-4a8d-b1a3-473f7d7701ad';  //TODO 上线之后需要配置
                                $code = Code::where('activity_uuid', $activity_uuid)->where('is_send', 0)->where('state', 1)->where('use_num', '>', 0)->first();
                                $code->update(['is_send' => 1]);
                                // 发送消息
                                $message = [];
                                $message['type'] = '112';//您的限时任务即将结束！
                                $message['place'] = '9';// 9是限定任务
                                $message['route_link'] = '/app/ActInfoActivity?params_data='.$activity_uuid;//此任务跳转路由
                                $message['owner_uuid'] = null;//空是系统发
                                $message['time_limit_task_name'] = $task->title;
                                $message['time_limit_task_promo_code'] = $code->code;
                                //接收者
                                $membersUuid = [$member->uuid];
                                MessageService::sendMessage($message, $membersUuid);
                                break;
                            case 44:
                                $activity_uuid = env('APP_ENV') == 'pro' ? '6e10ac94-d3ec-4a8d-b1a3-473f7d7701ad' : '6e10ac94-d3ec-4a8d-b1a3-473f7d7701ad';  //TODO 上线之后需要配置
                                $code = Code::where('activity_uuid', $activity_uuid)->where('is_send', 0)->where('state', 1)->where('use_num', '>', 0)->first();
                                $code->update(['is_send' => 1]);

                                // 发送消息
                                $message = [];
                                $message['type'] = '112';//您的限时任务即将结束！
                                $message['place'] = '9';// 9是限定任务
                                $message['route_link'] = '/app/ActInfoActivity?params_data='.$activity_uuid;//此任务跳转路由
                                $message['owner_uuid'] = null;//空是系统发
                                $message['time_limit_task_name'] = $task->title;
                                $message['time_limit_task_promo_code'] = $code->code;
                                //接收者
                                $membersUuid = [$member->uuid];
                                MessageService::sendMessage($message, $membersUuid);
                                break;
                            case 45:
                                $activity_uuid = env('APP_ENV') == 'pro' ? '57f2685d-6b06-4460-bda4-dc7b931c16a4' : 'cc7a3229-2f4d-4eb9-bb74-8b45b9cd7880';  //TODO 上线之后需要配置
                                $code = Code::where('activity_uuid', $activity_uuid)->where('is_send', 0)->where('state', 1)->where('use_num', '>', 0)->first();
                                $code->update(['is_send' => 1]);

                                // 发送消息
                                $message = [];
                                $message['type'] = '112';//您的限时任务即将结束！
                                $message['place'] = '9';// 9是限定任务
                                $message['route_link'] = '/app/ActInfoActivity?params_data='.$activity_uuid;//此任务跳转路由
                                $message['owner_uuid'] = null;//空是系统发
                                $message['time_limit_task_name'] = $task->title;
                                $message['time_limit_task_promo_code'] = $code->code;
                                //接收者
                                $membersUuid = [$member->uuid];
                                MessageService::sendMessage($message, $membersUuid);
                                break;
                            case 46:
                                $activity_uuid = env('APP_ENV') == 'pro' ? '57f2685d-6b06-4460-bda4-dc7b931c16a4' : 'cc7a3229-2f4d-4eb9-bb74-8b45b9cd7880';  //TODO 上线之后需要配置
                                $code = Code::where('activity_uuid', $activity_uuid)->where('is_send', 0)->where('state', 1)->where('use_num', '>', 0)->first();
                                $code->update(['is_send' => 1]);

                                // 发送消息
                                $message = [];
                                $message['type'] = '112';//您的限时任务即将结束！
                                $message['place'] = '9';// 9是限定任务
                                $message['route_link'] = '/app/ActInfoActivity?params_data='.$activity_uuid;//此任务跳转路由
                                $message['owner_uuid'] = null;//空是系统发
                                $message['time_limit_task_name'] = $task->title;
                                $message['time_limit_task_promo_code'] = $code->code;
                                //接收者
                                $membersUuid = [$member->uuid];
                                MessageService::sendMessage($message, $membersUuid);
                                break;
                            default:
                                break;
                        }
                    }
                }
            };

            DB::commit();
        }catch (\Exception $e){
            DB::rollBack();
            dd($e);

            LogService::error($e->getMessage().'_'.$e->getLine());
            return false;
        }

        return true;
    }
}
